SuperStrict

Framework brl.basic
import brl.random
import brl.filesystem
import brl.system
import brl.map
import brl.stream

SeedRnd( Millisecs() )

Global MaxWordLen:Int = 30

Type TWordGen
	Field ChunkMap:TMap = New TMap
	Field WordLenRank:Int[] = New Int[ MaxWordLen ]
	Field WordRankTotal:Int
	Field WordMap:TMap = New TMap
	Field MinWordLen:Int = 3

	
	
	Function FromFile:TWordGen( Filename:String )
		Local WordGen:TWordGen = New TWordGen
		WordGen.LoadFromFile( Filename )
		Return WordGen
	End Function
	
	
	
	Method LoadFromFile( Filename:String )
		Local File:TStream = ReadFile( Filename )
		
		Local NumLine:String = ReadLine( File )
		Local N:Int = MinWordLen
		For Local S:String = Eachin NumLine.Split( "," ) 
			WordLenRank[ N ] = S.ToInt()
			WordRankTotal :+ WordLenRank[ N ]
			N :+ 1
		Next
		
		While Not EOF( File )
			Local NumLine:String = ReadLine( File )
			
			Local ChunkName:String = NumLine[ ..2 ]
		
			Local Chunk:TChunk = New TChunk
			ChunkMap.Insert( ChunkName, Chunk )
			'WriteLine( OFile, ChunkName )
			
			Chunk.EndTimes = NumLine[ 4.. ].ToInt()
						
			NumLine = ReadLine( File )
			N = 0
			For Local S:String = Eachin NumLine.Split( "," )
				Chunk.Chance[ N ] = S.ToInt()
				Chunk.Total :+ Chunk.Chance[ N ]
				N :+ 1
			Next
			
			'WriteLine( OFile, ChunkName + ": " + Chunk.Total +", " + Chunk.EndTimes )
			'If Not Chunk.CanBeEnd Then WriteLine( OFile, ChunkName )
		Wend
		
		CloseFile( File )
	End Method
	
	
	
	Function FromText:TWordGen( Filename:String, MinWordLen:Int = 3 )
		Local WordGen:TWordGen = New TWordGen
		WordGen.MinWordLen = MinWordLen
		WordGen.LoadFromText( Filename )
		Return WordGen
	End Function
	
	
	
	Method LoadFromText( Filename:String )
		Local File:TStream = ReadFile( Filename )
		
		While Not EOF( File )
			Local S:String = ReadLine( File ) + " "
			Local Word:String
			
			For Local N:Int = 0 Until Len( S )
				Local Sym:Int = S[ N ]
				
				If Sym >=192 Then
					If Sym < 224 Then Sym = Sym + 32
					Word :+ Chr( Sym )
				ElseIf Not WordMap.Contains( Word ) Then
					Local WordLen:Int = Len( Word )
					If WordLen >= MinWordLen And WordLen <= MaxWordLen Then WordMap.Insert( Word, Null )
					Word = ""
				End If
			Next
		Wend
		
		CloseFile( File )
		
		
		'File = WriteFile( "words.txt" )
		'For Local S:String = Eachin WordMap.Keys()
		'	WriteLine( FIle, S )
		'Next
		'CloseFile( File )
		
		
		For Local S:String = Eachin WordMap.Keys()
			WordLenRank[ Len( S ) ] :+1
			WordRankTotal :+ 1

			S = "  " + S
			
			Local Chunk:TChunk
			For Local N:Int = 0 Until Len( S ) - 2
				Chunk = TChunk( ChunkMap.ValueForKey( S[ N..N + 2 ] ) )
				If Not Chunk Then
					Chunk = New TChunk
					ChunkMap.Insert( S[ N..N + 2 ], Chunk )
				End If
				
				Chunk.Chance[ S[ N + 2 ] - 224 ] :+ 1
				
				Chunk.Total :+ 1
			Next
	
			Chunk = TChunk( ChunkMap.ValueForKey( S[ Len( S ) - 2.. ] ) )
			If Not Chunk Then
				Chunk = New TChunk
				ChunkMap.Insert( S[ Len( S ) - 2.. ], Chunk )
			End If
			Chunk.EndTimes :+ 1
		Next
	End Method
	

		
	Method Save( FileName:String )
		Local File:TStream = WriteFile( FileName )
		
		Local S:String = ""
		For Local N:Int = MinWordLen Until MaxWordLen
			S :+ "," + WordLenRank[ N ]
		Next
		WriteLine( File, S[ 1.. ] )
		
		For Local S:String = Eachin ChunkMap.Keys()
			Local Chunk:TChunk = TChunk( ChunkMap.ValueForKey( S ) )
			
			WriteLine( File, S + ": " + Chunk.EndTimes )
			
			S = ""
			For Local N:Int = Eachin Chunk.Chance
				S :+ "," + N
			Next
			
			WriteLine( File, S[ 1.. ] )
			'WriteLine( OFile, S + ": " + 1.0 * Chunk.Total / Chunk.EndTimes )
		Next
		CloseFile( File )
	End Method


		
	Method GenerateWord:String()
		Local WordLen:Int
		Local Word:String
			
		Repeat
			Local P:Int = Rand( 0, WordRankTotal - 1 )
			
			For WordLen = MinWordLen Until MaxWordLen
				P :- WordLenRank[ WordLen ]
				If P < 0 Then Exit
			Next
			'debugstop
				
			Local PrevChars:String = "  "
			Word = ""
		
			Local Tries:Int = 0
			Local LetterTries:Int
			For Local LetterNum:Int = 1 To WordLen
				Local Chunk:TChunk = TChunk( ChunkMap.ValueForKey( PrevChars ) )
				If Not Chunk Then Exit
				
				Local NewChars:String
				Local N:Int
				Local NewChunk:TChunk
				LetterTries = 0
				
				Repeat
					Local R:Int = Rand( 0, Chunk.Total - 1 )
					
					For N = 0 Until 32
						R :- Chunk.Chance[ N ]
						If R < 0 Then
							'debugstop
							NewChars = PrevChars[ 1.. ] + Chr( N + 224 )
							Exit
						End If
					Next
					
					NewChunk = TChunk( ChunkMap.ValueForKey( NewChars ) )
					If NewChunk Then
						If LetterNum < WordLen Then Exit
						If NewChunk.EndTimes Then
							Exit
						Else
							LetterTries :+ 1
						End If
					Else
						LetterTries :+ 1
					End If
					If LetterTries = 30 Then Exit
				Forever
				
				If LetterTries = 30 Then Exit
				
				'Debuglog Chr( "abwgdezzijklmnoprstufhchhh-y-eua"[ N ] ) + "," + wordlen + "," +letternum
				
				Word :+ Chr( N + 224 )
				'( 0.7 + 0.3 * LetterNum / WordLen ) * 
				If LetterNum >= MinWordLen And 1.0 * NewChunk.EndTimes / NewChunk.Total + Rnd( 0.1 ) > 0.62 Then Exit
				If LetterNum = WordLen And NewChunk.Total > 50 * NewChunk.EndTimes Then
					LetterNum :- 1
					Tries :+ 1
					If Tries = 30 Then Exit
				End If
				If LetterNum = WordLen Then Exit
				PrevChars = NewChars
				
			Next
			
			If LetterTries < 30 And Tries < 30 Then Exit
		Forever
		
		Return Word
	End Method
End Type



Type TChunk
	Field Chance:Int[] = New Int[ 32 ]
	Field Total:Int
	Field EndTimes:Byte = False
End Type


'Local OFile:TStream = WriteFile( "ch.txt" )
Local FileName:String = ""
'If AppArgs.Length > 1 Then FileName = AppArgs[ 1 ]

'Local WordGen:TWordGen = TWordGen.FromText( "word_rus.txt" )
'WordGen.Save( "chunks.voc" )



Local File:TStream = WriteFile( "output.txt" )

Select Proceed( "Yes - names, No - words from vocabulary, Cancel - words from text" )
	Case 1
		Local Names:TWordGen[] = New TWordGen[ 2 ]
		Local Patronyces:TWordGen[] = New TWordGen[ 2 ]
		Names[ 0 ] = TWordGen.FromText( "names_men.txt" )
		Names[ 1 ] = TWordGen.FromText( "names_wimen.txt" )
		Patronyces[ 0 ] = TWordGen.FromText( "patronyces_men.txt", 7 )
		Patronyces[ 1 ] = TWordGen.FromText( "patronyces_wimen.txt", 7 )
		Local Surnames:TWordGen = TWordGen.FromText( "surnames.txt", 5 )
		
		For Local WordNum:Int = 0 Until 256
			Local Index:Int = Rand( 0, 1 )
			Local Ending:String = ""
			If Index Then Ending = chr( 224 )
			
			'debugstop
			WriteLine( File, SurNames.GenerateWord() + Ending + " " + Names[ Index ].GenerateWord() + " " + Patronyces[ Index ].GenerateWord()  )
		Next
	Case 0
		Local WordGen:TWordGen = TWordGen.FromFile( "chunks.voc" )
		
		For Local WordNum:Int = 0 Until 256
			WriteLine( File, WordGen.GenerateWord() )
		Next
	Case -1
		Local WordGen:TWordGen = TWordGen.FromText( "example.txt" )
		
		For Local WordNum:Int = 0 Until 256
			WriteLine( File, WordGen.GenerateWord() )
		Next
End Select

CloseFile( File )

OpenURL( "output.txt" )
'debugstop